MPT Object page improvement - #1339
Conversation
| // Circulating supply = outstanding amount minus large (>= 20%) holders, except | ||
| // for RWA tokens where those holders are custodians/treasuries (no exclusion). | ||
| const isRwa = isRwaAssetClass( | ||
| mptokenIssuance?.parsedMPTMetadata?.asset_class as string | undefined, |
There was a problem hiding this comment.
Unsafe cast of free-form issuer JSON. Add runtime type guard before calling .trim():
const isRwa = typeof mptokenIssuance?.parsedMPTMetadata?.asset_class === 'string'
? isRwaAssetClass(mptokenIssuance.parsedMPTMetadata.asset_class as string)
: false
| mptokenIssuance?.parsedMPTMetadata?.asset_class as string | undefined, | |
| typeof mptokenIssuance?.parsedMPTMetadata?.asset_class === 'string' | |
| ? mptokenIssuance.parsedMPTMetadata.asset_class | |
| : undefined, |
|
|
||
| // Circulating supply = outstanding amount minus large (>= 20%) holders, except | ||
| // for RWA tokens where those holders are custodians/treasuries (no exclusion). | ||
| const isRwa = isRwaAssetClass( |
There was a problem hiding this comment.
Unsafe type cast—issuer JSON could be non-string, breaking .trim(). Add typeof guard:
const isRwa = isRwaAssetClass(
(typeof mptokenIssuance?.parsedMPTMetadata?.asset_class === 'string' ? mptokenIssuance.parsedMPTMetadata.asset_class : undefined),
)
There was a problem hiding this comment.
This is a well-scoped, well-tested fix for the four reported MPT object page display bugs plus a shared circulating-supply util extracted for both token pages. The BigInt-based supply math, RWA skip logic, registrable-domain parsing, and JsonView string-collapse fix all look correct and are backed by targeted unit tests that match the described before/after behavior. I did not find any high-confidence correctness or security issues in the added/changed lines.
…p as a registrable domain, keeping shortenDomain for NFT URLs
| @@ -1,48 +0,0 @@ | |||
| import { useMemo } from 'react' | |||
There was a problem hiding this comment.
Removed as it's dead code that isn't used anywhere.
| @@ -1,273 +0,0 @@ | |||
| import { renderHook } from '@testing-library/react' | |||
There was a problem hiding this comment.
Removed as it's dead code that isn't used anywhere.
| @@ -1,217 +0,0 @@ | |||
| import { | |||
There was a problem hiding this comment.
Removed as it's dead code that isn't used anywhere.
| @@ -1,38 +0,0 @@ | |||
| import { parseIntegerAmount } from '../../../shared/NumberFormattingUtils' | |||
There was a problem hiding this comment.
Removed as it's dead code that isn't used anywhere.
There was a problem hiding this comment.
Solid, well-tested fix for the MPT supply/circ-supply, issuer-name, metadata-truncation, and website-chip issues, with the shared BigInt-based circulating-supply util extracted cleanly from the IOU page. The one thing worth double-checking before merge is that the RWA detection (isRwaAssetClass) is a strict, case-sensitive equality check applied to two different data sources: a curated LOS field for IOU and raw on-chain metadata (written by arbitrary token issuers) for MPT. The tests explicitly lock in strict-only matching, so this looks intentional, but on-chain data isn't guaranteed to be spec-compliant the way a controlled backend field is — worth confirming with the author that this was a deliberate choice for the on-chain case specifically.
High Level Overview of Change
Fixes four reported display issues on the MPToken object page, and replaces the placeholder circulating-supply figure with a real calculation shared with the IOU page.
Supplyis now the on-chainOutstandingAmount;Circ Supplysubtracts holders owning ≥ 20% (skipped for RWA tokens). Fixes the reported "circulating supply > supply".franklintempleton.com) instead of a middle-truncated string that destroyed the TLD.Context of Change
Reported against livenet.xrpl.org/mpt/064E27366D15D1F5614B4D4E3183F835BCD62E7F6FD9FFD8 (Franklin
sgBENJI). Each root cause was confirmed against the liveledger_entry mpt_issuanceresponse rather than inferred.1. Circulating supply > supply. This issuance sets no
MaximumAmount, somaxAmtwasundefinedandMarketDatarenderedBigInt(maxAmt || '0')→ Supply = 0, while Circ Supply showed the real ~28.14. Per spec an unset maximum means the cap is2^63-1, which is meaningless to display.After product review the fix is: Supply =
OutstandingAmount, and Circ Supply = Supply minus holders ≥ 20% — the same rule the IOU page already applied. Large holders are issuer/treasury/whale wallets that are not meaningfully in circulation. The exclusion is skipped for RWA tokens (asset_class === 'rwa'), whose large holders are custodians; stablecoins are an RWA subclass and are covered by the same check.No new data source was required: the page already fetches the full holder set on-chain via
mpt_holders, with each holder'spercentcomputed againstOutstandingAmount.The subtraction runs in BigInt on unscaled amounts. A
Number-based version left float residue — for a fully-held token it produced values like2.3283064365386963e-10, whichparseAmountrenders as< 0.0001instead of0.00(~1/3 of fully-concentrated cases when fuzzed). BigInt also avoids silent precision loss for amounts near UInt64 max (~9.2e18), well beyond exact double precision.2. Truncated issuer name.
shortenAccount()— a 7…5 address truncator — was applied to the human-readable issuer name, rendering "Franklin Templeton Investments" as "Frankli…ments".3. Truncated metadata. The shared
JsonViewhard-codedcollapseStringsAfterLength={65}, clipping the 122-character URI in the metadata panel.4. Website chip destroyed the TLD.
shortenDomain(url, 12, 7)middle-truncates, producingwww.franklin…hnology. The TLD is the part users rely on to judge whether a link is safe, so the chip now shows the registrable domain parsed with a real public-suffix list (tldts) — correctly keepingthing.co.ukrather than collapsing it toco.uk.tldtswas already in the tree as a transitive dependency and is promoted to a direct one.Shared logic. The ≥20% and RWA rules now live in
Token/shared/utils/circulatingSupply.tsand are used by both token pages. IOU's calculation was promoted out of its component into that module so it can be unit-tested directly.Dead code.
IOU/hooks/useMarketCalculations.tsandIOU/utils/tokenCalculations.ts(plus their tests) were duplicates reachable only from their own tests — the shipping IOU page had its own copy.Type of Change
Codebase Modernization
All touched and new files are function components / TypeScript. New modules (
shared/domainUtils.ts,Token/shared/utils/circulatingSupply.ts,Token/MPT/utils/circulatingSupply.ts) are TypeScript.Before / After
Market Data box
0.00(noMaximumAmount)28.14(on-chainOutstandingAmount)28.14(> Supply)≤ Supply, excluding ≥20% holdersCirc Supply shows a spinner while holders load, and
--if that request fails — it never silently shows the unadjusted supply as if it were a real circulating figure.Header
Frankli…ments(truncated, in title)www.franklin…hnology(TLD destroyed)franklintempleton.com, full URL on hoverRule summary
asset_classsourceasset_class === 'rwa'asset_class === 'rwa'Stablecoins are an RWA subclass, so this single
asset_class === 'rwa'check covers them on both pages.Test Plan
Automated — all green:
npm run build-ts— no type errorsnpm run lint:ci— ESLint, Stylelint, Prettier (--max-warnings 0)npm run test:ci— 1708 tests pass, coverage above the 70/80 thresholdspre-commit run --all-filesnpm run build— production bundle builds with the new dependencyNew/updated tests:
Token/shared/test/utils/circulatingSupply.test.ts— threshold boundary (exactly 20%), large-holder subtraction,isRwaAssetClass(incl. case/whitespace), andcalculateIouCirculatingSupply(reported supply, supply fallback, RWA skip)Token/MPT/test/utils/circulatingSupply.test.ts— asset-scale handling, RWA skip, negative floor, and two exact-integer regressions: float residue →0, and amounts beyond double precisionshared/test/domainUtils.test.ts— registrable domain (incl.thing.co.uk), non-URL fallback, left-truncation preserving the TLDMarketData/Header/Metadata/GeneralOverview/DomainLink— Supply vs Circ Supply, spinner and--states, untruncated issuer name and metadata,titletooltipManual:
npm start, open/mpt/064E27366D15D1F5614B4D4E3183F835BCD62E7F6FD9FFD8— Supply is the full outstanding amount, Circ Supply is ≤ Supply (cross-check excluded accounts against Holders table rows with % ≥ 20), the chip readsfranklintempleton.comwith the full URL on hover, the issuer name renders in full, and the metadata URI is not clipped. IOU token pages show unchanged supply and market-cap values after the refactor.